﻿using Microsoft.EntityFrameworkCore;

namespace FlexField.Metadata.EntityFrameworkCore
{
    /// <summary>
    /// Base class for the Entity Framework database context used for metadata.
    /// </summary>
    public class MetadataFieldContext : MetadataFieldContext<string>
    {
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        protected MetadataFieldContext()
        {
        }

        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <param name="options"></param>
        public MetadataFieldContext(DbContextOptions options) : base(options)
        {
        }
    }

    /// <summary>
    /// Base class for the Entity Framework database context used for metadata.
    /// </summary>
    /// <typeparam name="TKey">The type of the primary key for fields.</typeparam>
    public class MetadataFieldContext<TKey> : DbContext where TKey : IEquatable<TKey>
    {
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        protected MetadataFieldContext()
        {
        }

        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <param name="options"></param>
        public MetadataFieldContext(DbContextOptions options) : base(options)
        {
        }

        /// <summary>
        /// Gets or sets the <see cref="DbSet{TEntity}"/> of Data Fields.
        /// </summary>
        public virtual DbSet<DataField<TKey>> DataFields { get; set; }

        /// <summary>
        /// Gets or sets the <see cref="DbSet{TEntity}"/> of Data Field Properties.
        /// </summary>
        public virtual DbSet<DataFieldProperty<TKey>> DataFieldProperties { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.Entity<DataField<TKey>>(b =>
            {
                b.HasKey(f => f.Id);
                b.HasIndex(f => new { TypeId = f.EntityId, f.NormalizedFieldName }).HasDatabaseName("FieldNameIndex").IsUnique();
                b.ToTable("MetadataFields");
                b.Property(f => f.ConcurrencyStamp).IsConcurrencyToken();
                b.Property(f => f.NormalizedFieldName).HasMaxLength(256).IsRequired();
                b.Property(f => f.FieldName).HasMaxLength(256);
                b.Property(f => f.DisplayName).HasMaxLength(256);
                b.Property(f => f.ValueType).HasMaxLength(256).IsRequired();
                b.HasMany(t => t.Properties).WithOne().HasForeignKey(p => p.FieldId).IsRequired();
            });

            builder.Entity<DataFieldProperty<TKey>>(b =>
            {
                b.HasKey(p => new { p.FieldId, p.NormalizedPropertyName });
                b.Property(p => p.NormalizedPropertyName).HasMaxLength(256).IsRequired();
                b.Property(p => p.PropertyName).HasMaxLength(256);
                b.ToTable("MetadataFieldProperties");
            });
        }
    }
}
